﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Facebook;
using Facebook.Session;
using Facebook.Rest;
using Facebook.Schema;
using Coot.Properties;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Threading;
using System.Xml;

namespace Coot
{
    /// <summary>
    /// Interaction logic for ScreenSaver.xaml
    /// </summary>
    public partial class ScreenSaver : Window
    {
        DesktopSession session;
        Api api;
        string sessionKey;
        string sessionSecret;
        long uid;
        GenericPhotoCollection photos;
        DispatcherTimer timer = new DispatcherTimer();
        PhotoCollection photoCollection;
        const string appKey = "490e4f4f0e12c48d96b8794aa3fcd3d1";
        readonly double screenWidth = SystemParameters.VirtualScreenWidth;
        readonly double screenHeight = SystemParameters.VirtualScreenHeight;
        readonly double screenLeft = SystemParameters.VirtualScreenLeft;
        readonly double screenTop = SystemParameters.VirtualScreenTop;
        TimeSpan time;
        GenericPhoto nextPhoto;
        BitmapImage nextBitmapImage;
        System.Windows.Point cursorStart;
        bool movedCursor = false;

        public ScreenSaver()
        {
            InitializeComponent();
            this.AllowsTransparency = Settings.Default.useTransparency;
            if (!AllowsTransparency)
                this.Background = new SolidColorBrush(Settings.Default.background);
            this.Left = screenLeft;
            this.Top = screenTop;
            this.Width = screenWidth;
            this.Height = screenHeight;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            System.Net.ServicePointManager.Expect100Continue = false;
            time = Settings.Default.time;
            photoCollection = new PhotoCollection(Settings.Default.numberOfPhotos);

            if (Settings.Default.photoSources == null || Settings.Default.photoSources.Count == 0)
            {
                refreshFacebookPhotos();
            }
            else if (Settings.Default.lastUpdate.AddHours(2).CompareTo(DateTime.UtcNow) < 0)
            {
                refreshFacebookPhotos();
            }
            else
            {
                photos = new GenericPhotoCollection(Settings.Default.photoSources, Settings.Default.photoCaptions, Settings.Default.photoWidths, Settings.Default.photoHeights);
            }

            timer.Tick += new EventHandler(timer_Tick);
            timer.Interval = time;

            preloadImage();
            timer.Start();
        }

        private void refreshFacebookPhotos()
        {
            sessionKey = Settings.Default.sessionKey;
            sessionSecret = Settings.Default.sessionSecret;
            uid = Settings.Default.uid;

            session = new DesktopSession(appKey, sessionSecret, sessionKey, true, new List<Enums.ExtendedPermissions>() { Enums.ExtendedPermissions.offline_access });
            api = new Api(session);

            Dictionary<string, string> queries = new Dictionary<string, string>();

            if (Settings.Default.taggedUids.Count > 0)
            {
                StringBuilder taggedQuery = new StringBuilder();
                taggedQuery.Append("SELECT src_big, caption, src_big_width, src_big_height FROM photo WHERE pid IN (SELECT pid FROM photo_tag WHERE subject = ");
                taggedQuery.Append(Settings.Default.taggedUids[0]);

                if (Settings.Default.taggedUids.Count > 1)
                {
                    for (int n = 1; n < Settings.Default.taggedUids.Count; n++)
                    {
                        taggedQuery.Append(" OR subject = ");
                        taggedQuery.Append(Settings.Default.taggedUids[n]);
                    }
                }

                taggedQuery.Append(") ORDER BY aid ASC");
                queries.Add("taggedPhotos", taggedQuery.ToString());
            }

            if (Settings.Default.selectedUids.Count > 0)
            {
                StringBuilder selectedQuery = new StringBuilder();
                selectedQuery.Append("SELECT src_big, caption, src_big_width, src_big_height FROM photo WHERE aid IN (SELECT aid FROM album WHERE owner = ");
                selectedQuery.Append(Settings.Default.selectedUids[0]);

                if (Settings.Default.taggedUids.Count > 1)
                {
                    for (int n = 1; n < Settings.Default.selectedUids.Count; n++)
                    {
                        selectedQuery.Append(" OR owner = ");
                        selectedQuery.Append(Settings.Default.selectedUids[n]);
                    }
                }

                selectedQuery.Append(") ORDER BY aid ASC");
                queries.Add("selectedPhotos", selectedQuery.ToString());
            }

            IList<fql_result> results = api.Fql.Multiquery(queries);

            photos = new GenericPhotoCollection();

            foreach (fql_result result in results)
            {
                XmlNodeList photoNodes = getXmlNodes(result.fql_result_set.CreateReader(), "photo");

                foreach (XmlNode node in photoNodes)
                {
                    photos.AddPhoto(node["src_big"].InnerText, node["caption"].InnerText, int.Parse(node["src_big_width"].InnerText), int.Parse(node["src_big_height"].InnerText));
                }
            }

            Settings.Default.photoSources = photos.GetSources();
            Settings.Default.photoCaptions = photos.GetCaptions();
            Settings.Default.photoWidths = photos.GetWidths();
            Settings.Default.photoHeights = photos.GetHeights();
            Settings.Default.lastUpdate = DateTime.UtcNow;
            Settings.Default.Save();
        }

        void bmp_DownloadCompleted(object sender, EventArgs e)
        {
            if (!timer.IsEnabled)
            {
                showImage();
                preloadImage();
                timer.Start();
            }
        }

        void timer_Tick(object sender, EventArgs e)
        {
            if (nextBitmapImage.IsDownloading)
            {
                timer.Stop();
            }
            else
            {
                showImage();
                preloadImage();
            }
        }

        private string getXmlValue(string xml, string key)
        {
            XmlDocument xDoc = new XmlDocument();
            xDoc.LoadXml(xml);
            XmlNodeList nodes = xDoc.GetElementsByTagName(key);
            return nodes[0].InnerText;
        }

        private string getXmlValue(XmlReader xml, string key)
        {
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(xml);
            XmlNodeList nodes = xDoc.GetElementsByTagName(key);
            return nodes[0].InnerText;
        }

        private XmlNodeList getXmlNodes(string xml, string key)
        {
            XmlDocument xDoc = new XmlDocument();
            xDoc.LoadXml(xml);
            return xDoc.GetElementsByTagName(key);
        }

        private XmlNodeList getXmlNodes(XmlReader xml, string key)
        {
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(xml);
            return xDoc.GetElementsByTagName(key);
        }

        private void preloadImage()
        {
            nextPhoto = photos.GetRandomPhoto();
            nextBitmapImage = new BitmapImage();
            nextBitmapImage.DownloadCompleted += new EventHandler(bmp_DownloadCompleted);
            nextBitmapImage.BeginInit();
            nextBitmapImage.UriSource = new Uri(nextPhoto.Source);
            nextBitmapImage.EndInit();
        }

        private void showImage()
        {
            nextBitmapImage.Freeze();
            photoCollection.AddPhoto(nextBitmapImage, nextPhoto.Width, nextPhoto.Height, nextPhoto.Caption);
            if (photoCollection.Full)
                viewGrid.Children.RemoveAt(0);
            viewGrid.Children.Add(photoCollection.Last());
        }

        private void Window_MouseMove(object sender, MouseEventArgs e)
        {
            System.Windows.Point cursorPosition = e.GetPosition(this);

            if (!movedCursor)
            {
                cursorStart = cursorPosition;
                movedCursor = true;
            }
            else
            {
                if (Math.Abs(cursorPosition.X - cursorStart.X) > 10)
                {
                    timer.Stop();
                    this.Close();
                }
                else if (Math.Abs(cursorPosition.Y - cursorStart.Y) > 10)
                {
                    timer.Stop();
                    this.Close();
                }
            }
        }

        private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
            timer.Stop();
            this.Close();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            timer.Stop();
            this.Close();
        }
    }
}
